<?php

namespace Xin\LaravelFortify\Model;

use Closure;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Str;
use Xin\Support\SQL;
use Xin\Support\Time;

/**
 * @method $this|Builder search(array $data)
 */
trait Search
{
	/**
	 * @var string[]
	 */
	protected array $searchMatchLikeFields = [];

	/**
	 * 搜索作用域
	 * @param Builder $query
	 * @param array $data
	 */
	public function scopeSearch(Builder $query, array $data)
	{
		$searchFields = static::getSearchFields();
		foreach ($searchFields as $key => $field) {
			if ($field instanceof Closure) {
				$field($this, $data[$key] ?? null, $data);
			} else {
				$value = $data[$field] ?? null;

				// 检测搜索器
				$fieldName = is_numeric($key) ? $field : $key;
				$method = 'search' . Str::studly($fieldName) . 'Attribute';
				if (method_exists($this, $method)) {
					$this->$method($query, $value, $data);
				} elseif ($value !== null) {
					if (in_array($fieldName, $this->searchMatchLikeFields, true)) {
						$query->where($fieldName, 'like', "%{$value}%");
					} else {
						$query->where($fieldName, $value);
					}
				}
			}
		}
	}

	/**
	 * 获取要搜索的字段列表
	 * @return array
	 */
	public static function getSearchFields()
	{
		$allowSearchFields = method_exists(static::class, 'getSimpleFields') ? static::getSimpleFields() : [];

		$keywordParameter = static::getSearchKeywordParameter();
		if ($keywordParameter) {
			return array_merge($allowSearchFields, is_array($keywordParameter) ? [
				$keywordParameter[0] => $keywordParameter[1],
			] : [$keywordParameter]);
		}

		return $allowSearchFields;
	}

	/**
	 * 获取关键字搜索参数
	 * @return string
	 */
	public static function getSearchKeywordParameter()
	{
		return "keywords";
	}

	/**
	 * 注册时间搜索器
	 * @param Builder $query
	 * @param string $value
	 * @return void
	 */
	public function searchCreatedAtAttribute(Builder $query, $value)
	{
		if (!$value) {
			return;
		}

		$value = Time::parseRange($value);
		$query->whereBetween('created_at', $value);
	}

	/**
	 * 标题搜索器
	 * @param Builder $query
	 * @param mixed $value
	 * @return void
	 */
	public function searchKeywordsAttribute(Builder $query, $value)
	{
		$values = SQL::keywords($value);
		if (empty($values)) {
			return;
		}

		$conditionExpressions = array_map(function ($key) use ($values) {
			return [$key, 'like', $values];
		}, static::getSearchKeywordFields());

		$query->where($conditionExpressions, null, null, 'or');
	}

	/**
	 * 获取关键字搜索字段
	 * @return string[]
	 */
	public static function getSearchKeywordFields()
	{
		return ["title", "content"];
	}

	/**
	 * 获取搜索器要匹配Like的字段
	 * @return array
	 */
	public function getSearchMatchLikeFields()
	{
		return $this->searchMatchLikeFields;
	}

	/**
	 * 设置搜索器要匹配Like的字段
	 * @return array
	 */
	public function setSearchMatchLikeFields($matchLikeFields)
	{
		return $this->searchMatchLikeFields = $matchLikeFields;
	}
}
